#include "HMAC.h"
#include <cstring>


void HMAC::init(const void *key, unsigned int size) {
	// init key (64-byte)
	if (size>64) {
		memcpy(mKey, mAlgorithm->digest(key, size), getSize());
		size = getSize();
	} else memcpy(mKey, key, size);
	// fill zero padding key
	if (size<64) memset(mKey+size, 0, 64-size);
	// set key ^ ipad (0x36) as istr
	uint32_t *istr = (uint32_t*) mKey;
	for(; istr<(uint32_t*)(mKey+64); ++istr)
		*istr = *istr ^ 0x36363636;
	// set istr as begin message
	mAlgorithm->init();
	mAlgorithm->update(mKey, 64);
}

void HMAC::update(const void *data, unsigned int size) {
	mAlgorithm->update(data, size);
}

void HMAC::final() {
	// get istr digest
	unsigned char istr[64];
	mAlgorithm->final();
	memcpy(istr, mAlgorithm->getDigest(), getSize());
	// recovery key with 0x36, then set key ^ opad(ox5c) as ostr
	uint32_t *ostr = (uint32_t*)mKey;
	for(; ostr<(uint32_t*)(mKey+64); ++ostr)
		*ostr = *ostr ^ 0x36363636 ^ 0x5c5c5c5c;
	// digest ostr
	mAlgorithm->init();
	mAlgorithm->update(mKey, 64);
	mAlgorithm->update(istr, getSize());
	mAlgorithm->final();
}
